package org.jeecg.modules.monitoring.j_monitoring.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.xkcoding.http.util.StringUtil;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.monitoring.j_monitoring.entity.*;
import org.jeecg.modules.monitoring.j_monitoring.entity.fdnEntity.Devices;
import org.jeecg.modules.monitoring.j_monitoring.entity.format.CabinetList;
import org.jeecg.modules.monitoring.j_monitoring.mapper.*;
import org.jeecg.modules.monitoring.j_monitoring.service.IMGlNetworkResourceService;
import org.jeecg.modules.monitoring.j_monitoring.service.IMGlStorageResourcesService;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @Description: 存储设备(管理)
 * @Author: xiaoyq
 * @Date:   2023-01-12
 * @Version: V1.0
 */
@Service
public class MGlStorageResourcesServiceImpl extends ServiceImpl<MGlStorageResourcesMapper, MGlStorageResources> implements IMGlStorageResourcesService {

	@Resource
	private MGlStorageResourcesMapper mGlStorageResourcesMapper;
	@Resource
	private MStorageCageMapper mStorageCageMapper;

	@Resource
	private MGlDriveCabinetMapper driveCabinetMapper;
	@Resource
	private MCabinetServiceImpl cabinetService;
	@Resource
	private MMachineRoomServiceImpl roomService;
	@Resource
	private MMachineRoomMapper mMachineRoomMapper;
	@Resource
	private MCabinetMapper cabinetMapper;
	@Resource
	private StorageAddLogMapper logMapper;


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveMain(MGlStorageResources mGlStorageResources, List<MStorageCage> mStorageCageList) {
		mGlStorageResourcesMapper.insert(mGlStorageResources);
		if(mStorageCageList!=null && mStorageCageList.size()>0) {
			for(MStorageCage entity:mStorageCageList) {
				//外键设置
				entity.setForeignKeyId(mGlStorageResources.getId());
				mStorageCageMapper.insert(entity);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateMain(MGlStorageResources mGlStorageResources,List<MStorageCage> mStorageCageList) {
		mGlStorageResourcesMapper.updateById(mGlStorageResources);

		//1.先删除子表数据
		mStorageCageMapper.deleteByMainId(mGlStorageResources.getId());

		//2.子表数据重新插入
		if(mStorageCageList!=null && mStorageCageList.size()>0) {
			for(MStorageCage entity:mStorageCageList) {
				//外键设置
				entity.setForeignKeyId(mGlStorageResources.getId());
				mStorageCageMapper.insert(entity);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delMain(String id) {
		mStorageCageMapper.deleteByMainId(id);
		mGlStorageResourcesMapper.deleteById(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delBatchMain(Collection<? extends Serializable> idList) {
		for(Serializable id:idList) {
			mStorageCageMapper.deleteByMainId(id.toString());
			mGlStorageResourcesMapper.deleteById(id);
		}
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public String getIp(String id) {
		MGlStorageResources resources = baseMapper.selectById(id);

		if (resources==null){
			return "";
		}
		return resources.getDeviceIp();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void edit(MGlStorageResources storageResources) {

		String json = storageResources.getCabinetList();
		if (!StringUtil.isEmpty(json)){
			List<CabinetList> list = JSONArray.parseArray(json, CabinetList.class);
			for(CabinetList cabinetList : list){
				MGlDriveCabinet cabinet = driveCabinetMapper.selectById(cabinetList.getCabinetId());
				if (cabinet==null){
					continue;
				}
				cabinet.setMountId(storageResources.getId());
				cabinet.setMountName(storageResources.getName()+storageResources.getEquipmentNo());
				driveCabinetMapper.updateById(cabinet);
			}
		}

		baseMapper.updateById(storageResources);
	}

	@Override
	public JSONObject getDeviceMapById(String storageId) {
		MGlStorageResources storageResources = this.getById(storageId);
		if(storageResources==null){
			return null;
		}
		JSONObject parent,child,result = new JSONObject();
		result.put("type","交换机");
		IMGlNetworkResourceService mGlNetworkResourceService = ApplicationContextUtil.getContext().getBean(IMGlNetworkResourceService.class);
		MGlNetworkResource glNetworkResource;
		if(storageResources.getUplinkOpticalSwitchId()!=null && !"".equals(storageResources.getUplinkOpticalSwitchId())){
			result.put("id",storageResources.getUplinkOpticalSwitchId());
			result.put("title",storageResources.getUplinkOpticalSwitch());
			result.put("ip",storageResources.getDeviceIp());
		}
		else if(storageResources.getOnlineNetworkSwitchId()!=null && !"".equals(storageResources.getOnlineNetworkSwitchId())) {
			glNetworkResource = mGlNetworkResourceService.getById(storageResources.getOnlineNetworkSwitchId());
			String name = glNetworkResource!=null? glNetworkResource.getName():"";
			String ip = glNetworkResource!=null? glNetworkResource.getManageIp():"";
			result.put("id",storageResources.getOnlineNetworkSwitchId());
			result.put("title",name);
			result.put("ip",storageResources.getDeviceIp());
		}

		child = new JSONObject();
		child.put("type","存储");
		child.put("id",storageResources.getId());
		child.put("title",storageResources.getName());
		child.put("ip",storageResources.getDeviceIp());
		result.put("child",child);

		return result;
	}

	@Override
	public MGlStorageResources getBySwitchId(String uplinkOpticalSwitchId) {
		QueryWrapper<MGlStorageResources> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(MGlStorageResources::getUplinkOpticalSwitchId,uplinkOpticalSwitchId);
		List<MGlStorageResources> storageResourcesList = this.list(queryWrapper);
		if(storageResourcesList.size()==0){
			return null;
		}
		return storageResourcesList.get(0);
	}


	public boolean saveBatch(Collection<MGlStorageResources> entityList, int size){

		//机柜列表
		List<MCabinet> cabinetList = cabinetMapper.selectAll();

		//机房列表
		List<MMachineRoom> roomList = mMachineRoomMapper.selectAll();

		//处理机房机柜id绑定问题
		for (MGlStorageResources entity : entityList){
			entity.setCabinetId(cabinetService.getId(entity.getCabinet(),cabinetList));
			entity.setMachineRoomId(roomService.getId(entity.getMachineRoom(),roomList));
		}


		String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
		return this.executeBatch(entityList, size, (sqlSession, entity) -> {
			sqlSession.insert(sqlStatement, entity);
		});

	}


	public List<MGlStorageResources> getMonitorList(){

		QueryWrapper<MGlStorageResources> queryWrapper = new QueryWrapper();
		queryWrapper.eq("whether_to_monitor","1");
		return baseMapper.selectList(queryWrapper);
	}


	public List analysis(MGlStorageResources storageResources){
		List<MGlStorageResources> selectList = this.getMonitorList();
		List<Map<String,Object>> resultList = new ArrayList<>();

		for (MGlStorageResources resources : selectList){
			Map<String,Object> map = new HashMap<>();
			map.put("name",resources.getName());
			map.put("id",resources.getId());
			map.put("model",resources.getModel());
			map.put("cabinet",resources.getCabinet());
			map.put("deviceIp",resources.getDeviceIp());
			map.put("singleHardDiskNo",resources.getSingleHardDiskNo());
			map.put("singleHardDiskCount",resources.getSingleHardDiskCount());
			map.put("usedCapacity",resources.getUsedCapacity());

			BigDecimal residue = resources.getSingleHardDiskCount().subtract(resources.getUsedCapacity());
			map.put("residue",resources.getSingleHardDiskCount().subtract(resources.getUsedCapacity()));


			//echart图标数据
			List<StorageAddLog> logList = logMapper.selectByStorageId(resources.getId());

			map.put("monthData", logList);
			//计算几个月资源耗尽
//			Collections.reverse(logList);
			map.put("monthNum", this.getMonthOver(logList, residue));

			resultList.add(map);
		}

		return resultList;
	}

	public Integer getMonthOver(List<StorageAddLog> logList, BigDecimal residue) {

		if (logList.size() == 0) {
			return 0;
		}

		BigDecimal addCountNum = new BigDecimal(0);
		for (int i = 0; i <= logList.size() - 1; i++) {
			StorageAddLog log = logList.get(i);
			//取三个月
			if (i <= 2) {
				addCountNum = addCountNum.add(log.getAddNum());
			}
		}

		if (addCountNum.compareTo(BigDecimal.ZERO) > 0 && residue.compareTo(BigDecimal.ZERO)>0) {
			addCountNum = addCountNum.divide(new BigDecimal(3),2,BigDecimal.ROUND_HALF_UP);
			return residue.divide(addCountNum,2,BigDecimal.ROUND_HALF_UP).setScale(0, RoundingMode.UP).intValue();
		}

		return 0;
	}


	public void syncAddLog(){
		List<MGlStorageResources> newList = this.getMonitorList();


		List<StorageAddLog> lastList = logMapper.selectLastTimeData(DateUtils.getBeginMonth());

		List<StorageAddLog> logList = new ArrayList<>();
		for(MGlStorageResources storageResources : newList ){

			StorageAddLog log = new StorageAddLog();

			logMapper.deleteByRecordTimeAndStorageId(DateUtils.getBeginMonth(),storageResources.getId());
			log.setId(UUID.randomUUID().toString().replace("-", ""));

			log.setResidueNum(storageResources.getUsedCapacity());
			log.setAddNum(this.getAddNum(lastList,storageResources));

			log.setStorageId(storageResources.getId());
			log.setRecordTime(DateUtils.getBeginMonthDate());

			logList.add(log);
		}

		if (logList.size()>0){
			logMapper.insertBatch(logList);
		}


	}

	public BigDecimal getAddNum(List<StorageAddLog> lastList , MGlStorageResources storageResources){

		BigDecimal res = new BigDecimal(0);
		Boolean isnew = true;

		for (StorageAddLog log1 : lastList){


			if (log1.getStorageId().equals(storageResources.getId())){
				isnew = false;//处理是否不存在
				if (storageResources.getUsedCapacity() != null && log1.getResidueNum() != null ){
					res = storageResources.getUsedCapacity().subtract(log1.getResidueNum());

					if (res.compareTo(BigDecimal.ZERO) < 0){
						return new BigDecimal(0);
					}

				}

			}

		}

		if (isnew){
			return storageResources.getUsedCapacity() == null ? new BigDecimal(0) : storageResources.getUsedCapacity();
		}

		return res;
	}


}
